package com.hitqz.robot.driver.netty.protocol.decoder;

import com.hitqz.robot.driver.dto.robot.MessageRobotDto;
import com.hitqz.robot.api.common.util.ByteUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 机器人控制信息的解码器
 * @author xupkun
 * @date 2023/8/4
 */
@Slf4j
public class RobotControllerDecoder extends ByteToMessageDecoder {

    private MessageRobotDto lastRobotDto;

    private int readMaxTimes = 0;


    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        try {
            boolean add = false;
            if (lastRobotDto != null) {
                readMaxTimes++;
                //if (readMaxTimes >= canReadMaxTimes) {
                //    log.info("lastDto: {}--{}", lastRobotDto.getDataLength(), lastRobotDto.getResetLength());
                //    lastRobotDto = null;
                //    byteBuf.readBytes(byteBuf.readableBytes());
                //    byteBuf.resetReaderIndex();
                //    byteBuf.clear();
                //    readMaxTimes = 0;
                //    return;
                //}
                int resetReadLength = lastRobotDto.getResetLength();
                int readLength = lastRobotDto.getResetLength();
                if (resetReadLength > byteBuf.readableBytes()) {
                    readLength = byteBuf.readableBytes();
                }
                byte[] restBytes = new byte[readLength];
                byteBuf.readBytes(restBytes);
                ByteBuffer buffer = ByteBuffer.allocate(lastRobotDto.getLastByte().length + readLength);
                buffer.put(lastRobotDto.getLastByte());
                buffer.put(restBytes);
                byte[] data = buffer.array();
                if (resetReadLength == readLength) {
                    lastRobotDto.setData(new String(data, StandardCharsets.UTF_8));
                    add = true;
                    readMaxTimes = 0;
                } else {
                    lastRobotDto.setLastByte(data);
                    lastRobotDto.setResetLength(resetReadLength - readLength);
                }
            } else {
                if (byteBuf.readableBytes() > 4) {
                    // 读取头部
                    while (true) {
                        // 标记开始的index
                        byteBuf.markReaderIndex();
                        // 读取了协议的开始标志
                        int head = byteBuf.readByte();
                        if (head == 0x5A) {
                            break;
                        }

                        //5a 01 00 00 00 00 1f 5f 4b 65 24 55 00 00 00 00 7b 22 44 49 22 3a 5b 7b 22 69 64 22 3a 30 2c 22 73 6f 75 72 63 65 22 3a 22 6e 6f 72 6d 61 6c 22 2c 22 73 74 61 74 75 73 22 3a 66 61 6c 73 65 2c 22 76 61 6c 69 64 22 3a 74 72 75 65 7d 2c 7b 22 69 64 22 3a 31 2c 22 73 6f 75 72 63 65 22 3a 22 6e 6f 72 6d 61 6c 22 2c 22 73 74 61 74 75 73 22 3a 66 61 6c 73 65 2c 22 76 61 6c 69 64 22 3a 74 72 75 65 7d 2c 7b 22 69 64 22 3a 32 2c 22 73 6f 75 72 63 65 22 3a 22 6e 6f 72 6d 61 6c 22 2c 22 73 74 61 74 75 73 22 3a 66 61 6c 73 65 2c 22 76 61 6c 69 64 22 3a 74 72 75 65 7d 2c 7b 22 69 64 22 3a 33 2c 22 73 6f 75 72 63 65 22 3a 22 6e 6f 72 6d 61 6c 22 2c 22 73 74 61 74 75 73 22 3a 66 61 6c 73 65 2c 22 76 61 6c 69 64 22 3a 74 72 75 65 7d 2c 7b 22 69 64 22
                        //5f 66 72 6f 6e 74 5f 6c 69 6e 65 61 72 22 2c 22 70 61 73 73 69 76 65 22 3a 66 61 6c 73 65 2c 22 70 6f 73 69 74 69 6f 6e 22 3a 2d 34 35 37 2e 33 30 31 34 38 33 2c 22 72 61 77 5f 70 6f 73 69 74 69 6f 6e 22 3a 2d 34 35 37 2e 33 30 31 34 38 33 2c 22 73 70 65 65 64 22 3a 30 2c 22 73 74 6f 70 22 3a 74 72 75 65 2c 22 74 65 6d 70 65 72 61 74 75 72 65 22 3a 30 2c
                        // 未读取到包头
                        // 跳过一个字节去读取
                        byteBuf.resetReaderIndex();
                        byteBuf.readByte();
                        // 跳过之后 判断数据长度
                        if (byteBuf.readableBytes() == 0) {
                            return;
                        }
                    }
                    int version = byteBuf.readByte();
                    if (version != 1) {
                        byteBuf.readBytes(byteBuf.readableBytes());
                        byteBuf.resetReaderIndex();
                        byteBuf.clear();
                        return;
                    }
                    short sn = byteBuf.readShort();
                    byte[] dataLengthByte = new byte[4];
                    byteBuf.readBytes(dataLengthByte);
                    int dataLength = ByteUtil.bytes2IntBig(dataLengthByte);
                    short cmd = byteBuf.readShort();
                    byte[] innerData = new byte[6];
                    byteBuf.readBytes(innerData);
                    byte[] data = new byte[dataLength];
                    int restLength = byteBuf.readableBytes();
                    //log.info("resetLen: " + restLength);
                    if (restLength <= dataLength) {
                        //log.info("给下一个");
                        lastRobotDto = new MessageRobotDto(sn, cmd, null);
                        data = new byte[restLength];
                        byteBuf.readBytes(data);
                        lastRobotDto.setLastByte(data);
                        lastRobotDto.setResetLength(dataLength - restLength);
                    } else {
                        //log.info("直接读取完成");
                        byteBuf.readBytes(data);
                        lastRobotDto = new MessageRobotDto(sn, cmd, new String(data, StandardCharsets.UTF_8));
                        add = true;
                    }
                }
            }
            if (add) {
                list.add(lastRobotDto);
                lastRobotDto = null;
                readMaxTimes = 0;
            }
        } catch (Exception e) {
            log.info("数据发生异常" +e.getMessage());
            byteBuf.readBytes(byteBuf.readableBytes());
            byteBuf.resetReaderIndex();
            byteBuf.clear();
        }
    }

}
